package com.cloudkinto.service.order.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cloudkinto.bo.order.OrderMbQueryBo;
import com.cloudkinto.bo.order.OrderMbUpdateAccountSecretBo;
import com.cloudkinto.common.constant.SysConstant;
import com.cloudkinto.common.exception.BizException;
import com.cloudkinto.common.utils.StringsUtil;
import com.cloudkinto.common.web.PageResult;
import com.cloudkinto.common.web.SingleResult;
import com.cloudkinto.dao.OrderMabangDao;
import com.cloudkinto.entity.*;
import com.cloudkinto.service.company.CompanyService;
import com.cloudkinto.service.finance.CompanyAccountService;
import com.cloudkinto.service.order.OrderMabangService;
import com.cloudkinto.service.order.vo.mabang.*;
import com.cloudkinto.service.orderoutput.OrderOutputService;
import com.cloudkinto.service.orderoutput.vo.OrderOutputAddReq;
import com.cloudkinto.service.orderoutput.vo.OrderOutputPackageAddReq;
import com.cloudkinto.service.orderoutput.vo.OrderOutputProductAddReq;
import com.cloudkinto.service.product.ProductInfoService;
import com.cloudkinto.service.shop.ShopService;
import com.cloudkinto.service.stock.StockRecordService;
import com.cloudkinto.service.storage.StorageService;
import com.cloudkinto.utils.BeanCopierUtils;
import lombok.extern.slf4j.Slf4j;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * <p>
 * 马帮mabang订单表(包含商品) service实现类
 * </p>
 *
 * @author hua
 * @since 2024-09-09
 */
@Service
@Transactional(rollbackFor = Exception.class)
@Slf4j
public class OrderMabangServiceImpl extends ServiceImpl<OrderMabangDao, OrderMabangDo> implements OrderMabangService {
    @Autowired
    private ShopService shopService;
    @Autowired
    private CompanyService companyService;
    @Autowired
    private ProductInfoService productService;
    @Autowired
    private OrderOutputService orderOutputService;
    @Autowired
    private StockRecordService stockRecordService;
    @Autowired
    private MabangConfig mabangConfig;
    @Autowired
    private ThreadPoolExecutor threadPoolExecutor;
    @Autowired
    private StorageService storageService;
    @Autowired
    private CompanyAccountService mAccountService;
    @Autowired
    private static String GETO_AUTH_INFO = "get-OAuth-Info";
    @Autowired
    private static String ORDER_DELIVERY_FAILED_ACTION = "changed-error-order";
    @Autowired
    private static String SYNC_ORDER_ACTION = "get-Order-Info";
    @Autowired
    private static String SEND_PRODUCT_INFO_ACTION = "send-hwc-product";

    private static final OkHttpClient CLIENT;

    static {
        OkHttpClient.Builder builder = new OkHttpClient.Builder();
        CLIENT = builder.readTimeout(30, TimeUnit.SECONDS)
                .build();
    }


    @Override
    public SingleResult addInit() {
        return SingleResult.success("");
    }

    @Override
    public Object add(Object req, Long userId) {
        OrderMabangDo entityDo = new OrderMabangDo();
        BeanUtils.copyProperties(req, entityDo);
        baseMapper.insert(entityDo);
        return handlerAddAfter(entityDo);
    }

    //新增校验
    private void addCheck(Object req) {

    }

    //将新增的do转换成要返回的实体
    private Object handlerAddAfter(OrderMabangDo entityDo) {
        Object res = new Object();
        BeanUtils.copyProperties(entityDo, res);
        return res;
    }

    @Override
    public SingleResult updateInit(Long id) {
        return SingleResult.success("");
    }

    @Override
    public Object update(Object req, Long userId) {
        /*OrderMabangDo entityDo = dao.selectById(req.getId());
        BeanUtils.copyProperties(req, entityDo);
        handlerUpdateBefore(entityDo, userId);
        dao.updateById(entityDo);
        return handlerUpdateAfter(entityDo);*/
        return null;
    }

    //编辑校验
    private void updateCheck(Object req) {

    }

    //做修改之前要执行的业务定制处理
    private void handlerUpdateBefore(OrderMabangDo entityDo, Long userId) {
        entityDo.setUpdateTime(new Date());
    }

    //做修改之后要执行的业务定制处理
    private Object handlerUpdateAfter(OrderMabangDo entityDo) {
        Object res = new Object();
        BeanUtils.copyProperties(entityDo, res);
        return res;
    }

    @Override
    public int delete(Long id, Long userId) {
        return baseMapper.deleteById(id);
    }


    @Override
    public Object detail(Long id) {
        OrderMabangDo entityDo = baseMapper.selectById(id);
        Object res = new Object();
        BeanUtils.copyProperties(entityDo, res);
        return handlerDetailAfter(res);
    }

    //查询明细之后要执行的业务定制处理
    private Object handlerDetailAfter(Object res) {
        return res;
    }

    @Override
    public SingleResult pageInit(Long companyId) {
        Map<String, Object> map = new HashMap<>();
        map.put("shopList", shopService.getShopList(companyId));
        map.put("companyList", companyService.getCompanyList());
        map.put("warehouseCode", WarehouseCodeEnum.getCodeMap());
        return SingleResult.success(map);
    }

    @Override
    public PageResult getListPage(OrderMbQueryBo bo) {
        LambdaQueryWrapper<OrderMabangDo> lqw = queryBuild(bo);
        IPage<OrderMabangDo> page = new Page<>(bo.getCurrent(), bo.getPageSize());
        page = this.page(page, lqw);
        List<MabangOrderVo> orderList = BeanCopierUtils.listCopyMapper(page.getRecords(), OrderMabangDo.class, MabangOrderVo.class);
        handlerListAfter(orderList);
        return new PageResult(orderList, (int) page.getCurrent(), (int) page.getSize(), (int) page.getTotal(), (int) page.getPages());
    }

    /**
     * 查询分页列表之后对列表数据的处理
     */
    private void handlerListAfter(List<MabangOrderVo> list) {
        if (CollUtil.isEmpty(list)) {
            return;
        }
        List<Long> storageIdSet = list.stream().map(MabangOrderVo::getStorageId).filter(Objects::nonNull).collect(Collectors.toList());
        Map<Long, String> storageIdMatchName = new HashMap<>(8);
        if (CollUtil.isNotEmpty(storageIdSet)) {
            storageIdMatchName = storageService.listByIds(storageIdSet).stream().collect(Collectors.toMap(StorageDo::getId, StorageDo::getStorageName));
        }
        for (MabangOrderVo item : list) {
            item.setStorageName(storageIdMatchName.getOrDefault(item.getStorageId(), "GLC"));
            item.setAddress(
                    item.getProvince() + item.getCity() + item.getArea()
                            + (StringUtils.isNotBlank(item.getStreet1()) ? item.getStreet1() : "")
                            + (StringUtils.isNotBlank(item.getStreet2()) ? item.getStreet2() : "")
                            + (StringUtils.isNotBlank(item.getDoorcode()) ? item.getDoorcode() : "")
            );
        }
    }

    @Override
    public SingleResult<String> updateMbAccessToken(OrderMbUpdateAccountSecretBo bo, Long companyId) {
        String accessToken = bo.getAccessToken();
        Long storageId = bo.getStorageId();
        if (StringUtils.isBlank(accessToken) || Objects.isNull(storageId)) {
            return SingleResult.failure("参数不可为空");
        }
        CompanyDo companyDo = companyService.getById(companyId);
        if (Objects.isNull(companyDo)) {
            return SingleResult.failure("找不到公司信息,请先绑定公司");
        }
        MaBangAuthDto maBangAuthDto = MaBangAuthDto.builder().storageId(storageId).accessToken(accessToken).build();
        String oldAccessTokenJsonList = companyDo.getMbAccessToken();
        String newAccessTokenJsonList;
        if (StringUtils.isBlank(oldAccessTokenJsonList)) {
            newAccessTokenJsonList = JSONUtil.toJsonStr(Collections.singletonList(maBangAuthDto));
        } else {
            try {
                List<MaBangAuthDto> maBangAuthDtoList = JSONUtil.toList(oldAccessTokenJsonList, MaBangAuthDto.class);
                maBangAuthDtoList.add(maBangAuthDto);
                newAccessTokenJsonList = JSONUtil.toJsonStr(maBangAuthDtoList);
            } catch (Exception e) {
                log.info("获取马帮mabang可以授权的仓库列表时发现老版本授权，已做清除处理");
                newAccessTokenJsonList = JSONUtil.toJsonStr(Collections.singletonList(maBangAuthDto));
            }
        }
        companyDo.setMbAccessToken(newAccessTokenJsonList);
        companyDo.setUpdateTime(new Date());
        boolean update = companyService.updateById(companyDo);
        if (update) {
            return SingleResult.success(accessToken);
        } else {
            return SingleResult.failure("更新失败");
        }
    }

    @Override
    public SingleResult<String> mbAuthorize(Long companyId, Long storageId) {
        CompanyDo companyDo = companyService.getById(companyId);
        if (Objects.isNull(companyDo)) {
            return SingleResult.failure("找不到公司信息,请先绑定公司");
        }
        StorageDo storageDo = storageService.getById(storageId);
        if (Objects.isNull(storageDo) || StringUtils.isBlank(storageDo.getMbAppKey()) || StringUtils.isBlank(storageDo.getMbToken())) {
            log.error("马帮授权出现异常，原因：公司id:" + companyId + "的仓库:" + storageId + "的MbAppKey或MbToken为空");
            throw new BizException("仓库:" + storageId + "马帮数据校验异常，请联系系统管理员");
        }
        JSONObject data = new JSONObject();
        data.put("tCompanyId", companyId);
        data.put("redirectUrl", mabangConfig.getCallbackUrl() + "?storageId=" + storageId);
        JSONObject reqData = new JSONObject();
        reqData.put("sysData", buildMabangApiSysData(storageDo.getMbToken(), storageDo.getMbAppKey(), null, GETO_AUTH_INFO));
        reqData.put("data", data);
        okhttp3.RequestBody body = okhttp3.RequestBody.create(MediaType.parse("application/json; charset=utf-8"), reqData.toJSONString());
        Request request = new Request.Builder()
                .url(mabangConfig.getApiUrl())
                .post(body)
                .build();
        try (Response response = CLIENT.newCall(request).execute()) {
            if (!response.isSuccessful()) {
                throw new IOException("Unexpected code " + response);
            }
            JSONObject res = JSONObject.parseObject(response.body().string());
            if (!"10001".equals(res.getString("code"))) {
                return SingleResult.failure(res.getString("msg"));
            }
            JSONObject resData = res.getJSONObject("data");
            String oatherUrl = resData.getString("url");
            return SingleResult.success("授权成功", oatherUrl);
        } catch (IOException e) {
            log.error("授权失败", e);
        }
        return SingleResult.failure("授权失败");
    }

    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public SingleResult mbOrderSync(Long companyId, Date startDate, Date endDate) {
        CompanyDo companyDo = companyService.getById(companyId);
        if (Objects.isNull(companyDo)) {
            return SingleResult.failure("找不到公司信息,请先绑定公司");
        }
        String accessTokenJsonList = companyDo.getMbAccessToken();
        if (StringUtils.isBlank(accessTokenJsonList)) {
            return SingleResult.failure("请先授权");
        }
        List<MaBangAuthDto> maBangAuthDtoList;
        try {
            maBangAuthDtoList = JSONUtil.toList(accessTokenJsonList, MaBangAuthDto.class);
        } catch (Exception e) {
            return SingleResult.failure("授权错误，请重新授权");
        }
        if (CollUtil.isEmpty(maBangAuthDtoList)) {
            return SingleResult.failure("请先授权");
        }
        List<CompletableFuture<Void>> futures = new ArrayList<>();
        for (MaBangAuthDto maBangAuthDto : maBangAuthDtoList) {
            if (Objects.isNull(maBangAuthDto)) {
                continue;
            }
            Long storageId = maBangAuthDto.getStorageId();
            if (Objects.isNull(storageId)) {
                continue;
            }
            StorageDo storageDo = storageService.getById(storageId);
            if (Objects.isNull(storageDo)) {
                continue;
            }
            String mbAppKey = storageDo.getMbAppKey();
            String mbToken = storageDo.getMbToken();
            if (StrUtil.isBlank(mbAppKey) || StrUtil.isBlank(mbToken)) {
                continue;
            }
            String accessToken = maBangAuthDto.getAccessToken();
            if (StringUtils.isBlank(accessToken)) {
                continue;
            }
            CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
                List<String> successOrderIds = new ArrayList<>();
                Map<Long, String> errorOrderIds = new HashMap<>();
                int page = 1;
                int totalPage = 1;
                do {
                    JSONObject serviceData = new JSONObject();
                    serviceData.put("page", page);
                    if (Objects.nonNull(startDate) && Objects.nonNull(endDate)) {
                        serviceData.put("startTime", DateUtil.format(startDate, "yyyy-MM-dd 00:00:00"));
                        serviceData.put("endTime", DateUtil.format(endDate, "yyyy-MM-dd 23:59:59"));
                    }
                    JSONObject reqData = new JSONObject();
                    reqData.put("sysData", buildMabangApiSysData(mbToken, mbAppKey, accessToken, SYNC_ORDER_ACTION));
                    reqData.put("data", serviceData);
                    okhttp3.RequestBody body = okhttp3.RequestBody.create(MediaType.parse("application/json; charset=utf-8"), reqData.toJSONString());
                    Request request = new Request.Builder()
                            .url(mabangConfig.getApiUrl())
                            .post(body)
                            .build();
                    try (Response response = CLIENT.newCall(request).execute()) {
                        if (!response.isSuccessful()) {
                            log.error("同步马帮订单失败，原因：" + response.body().string());
                            return;
                        }
                        JSONObject res = JSONObject.parseObject(response.body().string());
                        if (!"10021".equals(res.getString("code"))) {
                            log.error("同步马帮订单失败，原因：" + res.getString("msg"));
                            return;
                        }
                        if (totalPage == 1) {
                            totalPage = res.getIntValue("page");
                        }
                        JSONObject data = res.getJSONObject("data");
                        String mbCompanyId = data.getString("companyId");
//                String compId = data.getString("tCompanyId");
                        List<MbOrderDetail> mbOrderDetails = data.getJSONArray("order").toJavaList(MbOrderDetail.class);
                        for (MbOrderDetail mbOrderDetail : mbOrderDetails) {
                            if (mbOrderDetail.getOrderItem() == null || mbOrderDetail.getOrderItem().isEmpty())
                                continue;
                            OrderMabangDo orderMabangDo = new OrderMabangDo();
                            BeanUtils.copyProperties(mbOrderDetail, orderMabangDo);
                            orderMabangDo.setStorageId(storageId);
                            orderMabangDo.setCompanyId(companyId);
                            orderMabangDo.setMbCompanyId(Long.valueOf(mbCompanyId));
                            orderMabangDo.setOrderDeliveryTime(mbOrderDetail.getCreateTime());
                            OrderMabangDo one = baseMapper.selectOne(
                                    Wrappers.<OrderMabangDo>lambdaQuery()
                                            .eq(OrderMabangDo::getOrderId, mbOrderDetail.getOrderId())
                                            .eq(OrderMabangDo::getCompanyId, companyId)
                                            .last("order by id desc limit 1")
                            );
                            if (Objects.isNull(one)) {
                                orderMabangDo.setOrderItem(JSONArray.toJSONString(mbOrderDetail.getOrderItem()));
                                orderMabangDo.setVendorId(mbOrderDetail.getVendorID());
                                orderMabangDo.setDeleteFlag(Boolean.FALSE);
                                orderMabangDo.setCreateTime(new Date());
                                baseMapper.insert(orderMabangDo);
                            }
                            //未出库状态，发送至筋斗云出库单
                            if (Objects.isNull(one) || one.getStatus() == 0) {
                                //发送至筋斗云出库单
                                OrderOutputAddReq orderOutputAddReq = buildOrderOutput(companyId, storageId, mbOrderDetail);
                                String value;
                                try {
                                    //校验余额是否不足
                                    if (!mAccountService.getIsDue(orderOutputAddReq.getCompanyId())) {
                                        value = (SysConstant.account_balance_insufficient);
                                    } else {
                                        value = orderOutputService.add(orderOutputAddReq, 1L);
                                    }
                                } catch (BizException e) {
                                    log.error("同步马帮订单失败，原因：", e);
                                    value = StringsUtil.createI18Message(e.getMessage());
                                }
                                if (value != null) {
                                    //添加失败，告知调用订单发货失败接口
                                    errorOrderIds.put(Long.valueOf(mbOrderDetail.getOrderId()), value);
                                } else {
                                    successOrderIds.add(orderMabangDo.getOrderId());
                                }
                            }
                        }
                    } catch (Exception e) {
                        log.error("同步马帮订单失败，原因：", e);
                    }
                } while (page++ < totalPage);
                //添加成功，批量修改状态
                if (CollUtil.isNotEmpty(successOrderIds)) {
                    this.lambdaUpdate()
                            .set(OrderMabangDo::getUpdateTime, new Date())
                            .set(OrderMabangDo::getStatus, 1)
                            .in(OrderMabangDo::getOrderId, successOrderIds)
                            .eq(OrderMabangDo::getCompanyId, companyId)
                            .update();
                }
                //添加失败，告知调用订单发货失败接口
                if (CollUtil.isNotEmpty(errorOrderIds)) {
                    changedErrorOrder(mbToken, mbAppKey, accessToken, errorOrderIds);
                }
            }, threadPoolExecutor);
            futures.add(future);
        }
        CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join();
        return SingleResult.success("同步成功");
    }

    /**
     * 同步商品至ERP
     *
     * @param companyId 公司id
     */
    @Override
    public SingleResult sendHwcProductToMabang(Long companyId) {
        CompanyDo companyDo = companyService.getById(companyId);
        if (Objects.isNull(companyDo)) {
            return SingleResult.failure("找不到公司信息,请先绑定公司");
        }
        String accessTokenJsonList = companyDo.getMbAccessToken();
        if (StringUtils.isBlank(accessTokenJsonList)) {
            return SingleResult.failure("请先授权");
        }
        List<MaBangAuthDto> maBangAuthDtoList;
        try {
            maBangAuthDtoList = JSONUtil.toList(accessTokenJsonList, MaBangAuthDto.class);
        } catch (Exception e) {
            return SingleResult.failure("授权错误，请重新授权");
        }
        if (CollUtil.isEmpty(maBangAuthDtoList)) {
            return SingleResult.failure("请先授权");
        }
        List<ProductInfoDo> productInfoList = productService.list(
                Wrappers.<ProductInfoDo>lambdaQuery().eq(ProductInfoDo::getCompanyId, companyId)
        );
        //获取商品库存(根据can_sell_count和freeze_count)
        List<Long> proIds = productInfoList.stream().map(ProductInfoDo::getId).collect(Collectors.toList());
        Map<Long, Integer> productExchangeStock = stockRecordService.list(
                Wrappers.<StockRecordDo>lambdaQuery().in(StockRecordDo::getProductInfoId, proIds)
                        .eq(StockRecordDo::getCompanyId, companyId)
        ).stream().collect(Collectors.groupingBy(
                        StockRecordDo::getProductInfoId,
                        Collectors.summingInt(item -> item.getCanSellCount() + item.getFreezeCount())
                )
        );
        JSONArray dataArr = new JSONArray();
        for (ProductInfoDo productInfoDo : productInfoList) {
            JSONObject data = new JSONObject();
            data.put("skuId", productInfoDo.getId());
            data.put("sku", productInfoDo.getCommoditySku());
            data.put("name", productInfoDo.getProductName());
            //库存
            data.put("inventory", productExchangeStock.getOrDefault(productInfoDo.getId(), 0));
            // data.put("specification", productInfoDo.getLength()
            //         + "cm * " + productInfoDo.getWidth()
            //         + "cm * " + productInfoDo.getHeight()
            //         + "cm -- " + productInfoDo.getWeight() + "kg");
            dataArr.add(data);
        }
        List<CompletableFuture<Void>> futures = new ArrayList<>();
        for (MaBangAuthDto maBangAuthDto : maBangAuthDtoList) {
            //todo 同步商品需确定是否需要不同仓库都同步一次
            if (Objects.isNull(maBangAuthDto)) {
                continue;
            }
            Long storageId = maBangAuthDto.getStorageId();
            if (Objects.isNull(storageId)) {
                continue;
            }
            StorageDo storageDo = storageService.getById(storageId);
            if (Objects.isNull(storageDo)) {
                continue;
            }
            String mbAppKey = storageDo.getMbAppKey();
            String mbToken = storageDo.getMbToken();
            if (StrUtil.isBlank(mbAppKey) || StrUtil.isBlank(mbToken)) {
                continue;
            }
            String accessToken = maBangAuthDto.getAccessToken();
            if (StringUtils.isBlank(accessToken)) {
                continue;
            }
            CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
                int start = 0;
                do {
                    JSONObject reqData = new JSONObject();
                    reqData.put("sysData", buildMabangApiSysData(mbToken, mbAppKey, accessToken, SEND_PRODUCT_INFO_ACTION));
                    reqData.put("data", dataArr.subList(start * 100, Math.min((start + 1) * 100, dataArr.size())));
                    okhttp3.RequestBody body = okhttp3.RequestBody.create(MediaType.parse("application/json; charset=utf-8"), reqData.toJSONString());
                    Request request = new Request.Builder()
                            .url(mabangConfig.getApiUrl())
                            .post(body)
                            .build();
                    try (Response response = CLIENT.newCall(request).execute()) {
                        if (!response.isSuccessful()) {
                            throw new IOException("Unexpected code " + response);
                        }
                        String string = response.body().string();
                        JSONObject jsonObject = JSONObject.parseObject(string);
                        if (!response.isSuccessful() && jsonObject.getIntValue("code") != 10041) {
                            throw new IOException("Unexpected code " + response);
                        }
                    } catch (IOException e) {
                        log.error("同步商品至mb ERP失败，原因：" + e.getMessage());
                    }
                    start++;
                } while (start * 100 < dataArr.size());
            }, threadPoolExecutor);
            futures.add(future);
        }
        CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join();
        return SingleResult.success("同步商品成功");
    }

    @Override
    public SingleResult<Boolean> checkAuth(Long companyId) {
        CompanyDo companyDo = companyService.getById(companyId);
        if (Objects.isNull(companyDo)) {
            return SingleResult.failure("找不到公司信息,请先绑定公司");
        }
        if (StringUtils.isNotBlank(companyDo.getMbAccessToken())) {
            return SingleResult.success(true);
        } else {
            return SingleResult.success(false);
        }
    }

    @Override
    public List<MbAuthStorageVo> getMbAuthStorageList(Long companyId) {
        List<StorageDo> storageDoList = storageService.list(Wrappers.<StorageDo>lambdaQuery().isNotNull(StorageDo::getMbAppKey).isNotNull(StorageDo::getMbToken));
        CompanyDo companyDo = companyService.getById(companyId);
        if (Objects.isNull(companyDo)) {
            throw new BizException("找不到公司信息,请先绑定公司");
        }
        String accessTokenJsonList = companyDo.getMbAccessToken();
        List<MbAuthStorageVo> result = new ArrayList<>();
        if (StringUtils.isBlank(accessTokenJsonList)) {
            for (StorageDo storageDo : storageDoList) {
                result.add(MbAuthStorageVo.builder().storageId(storageDo.getId()).storageName(storageDo.getStorageName()).isAuth(false).build());
            }
        } else {
            Map<Long, String> storageIdMatchAccessToken;
            try {
                storageIdMatchAccessToken = JSONUtil.toList(accessTokenJsonList, MaBangAuthDto.class).stream().collect(Collectors.toMap(MaBangAuthDto::getStorageId, MaBangAuthDto::getAccessToken));
            } catch (Exception e) {
                log.info("获取马帮mabang可以授权的仓库列表时发现老版本授权，已做清除处理");
                companyService.lambdaUpdate()
                        .eq(CompanyDo::getId, companyId)
                        .set(CompanyDo::getMbAccessToken, null)
                        .update();
                for (StorageDo storageDo : storageDoList) {
                    result.add(MbAuthStorageVo.builder().storageId(storageDo.getId()).storageName(storageDo.getStorageName()).isAuth(false).build());
                }
                return result;
            }
            for (StorageDo storageDo : storageDoList) {
                String accessToken = storageIdMatchAccessToken.get(storageDo.getId());
                result.add(MbAuthStorageVo.builder().storageId(storageDo.getId()).storageName(storageDo.getStorageName()).isAuth(StrUtil.isNotBlank(accessToken)).build());
            }
        }
        return result;
    }

    /**
     * 回传发货失败订单
     */
    private void changedErrorOrder(String mbToken, String mbAppKey, String accessToken, Map<Long, String> errorOrder) {
        if (StringUtils.isBlank(accessToken) || StringUtils.isBlank(mbToken) || StringUtils.isBlank(mbAppKey)) {
            log.warn("回传发货失败中断，原因：accessToken或token或appKey为空");
            return;
        }
        JSONArray dataArr = new JSONArray();
        for (Map.Entry<Long, String> entry : errorOrder.entrySet()) {
            JSONObject data = new JSONObject();
            data.put("orderId", entry.getKey());
            data.put("errorMessage", entry.getValue());
            dataArr.add(data);
        }
        JSONObject reqData = new JSONObject();
        reqData.put("sysData", buildMabangApiSysData(mbToken, mbAppKey, accessToken, ORDER_DELIVERY_FAILED_ACTION));
        reqData.put("data", dataArr);
        okhttp3.RequestBody body = okhttp3.RequestBody.create(MediaType.parse("application/json; charset=utf-8"), reqData.toJSONString());
        Request request = new Request.Builder()
                .url(mabangConfig.getApiUrl())
                .post(body)
                .build();
        try (Response response = CLIENT.newCall(request).execute()) {
            if (!response.isSuccessful()) {
                if (Objects.nonNull(response.body())) {
                    log.error("回传订单发货失败出现异常，原因：" + response.body());
                } else {
                    log.error("回传订单发货失败出现异常，原因：" + response.message());
                }
            }
        } catch (Exception e) {
            log.error("回传订单发货失败出现异常，原因：", e);
        }

    }

    /**
     * 构建mabang公共请求数据
     */
    private JSONObject buildMabangApiSysData(String token, String appKey, String accessToken, String action) {
        JSONObject sysData = new JSONObject();
        if (StringUtils.isNotBlank(accessToken)) {
            sysData.put("accessToken", accessToken);
        }
        sysData.put("token", token);
        sysData.put("appKey", appKey);
        sysData.put("action", action);
        sysData.put("version", "v1");
        return sysData;
    }

    private OrderOutputAddReq buildOrderOutput(Long companyId, Long storageId, MbOrderDetail mbOrderDetail) {
        OrderOutputAddReq req = new OrderOutputAddReq();
        BeanUtils.copyProperties(mbOrderDetail, req);
        req.setAddress(
                mbOrderDetail.getProvince()
                        + mbOrderDetail.getCity()
                        + mbOrderDetail.getArea()
                        + (StringUtils.isNotBlank(mbOrderDetail.getStreet1()) ? mbOrderDetail.getStreet1() : "")
                        + (StringUtils.isNotBlank(mbOrderDetail.getStreet2()) ? mbOrderDetail.getStreet2() : "")
                        + (StringUtils.isNotBlank(mbOrderDetail.getDoorcode()) ? mbOrderDetail.getDoorcode() : "")
        );
        List<OrderOutputPackageAddReq> packageAddReqs = new ArrayList<>();
        List<OrderOutputProductAddReq> productAddReqs = new ArrayList<>();
        if (mbOrderDetail != null && mbOrderDetail.getOrderItem() != null) {
            for (MbOrderItem orderItem : mbOrderDetail.getOrderItem()) {
                OrderOutputProductAddReq productAddReq = new OrderOutputProductAddReq();
                String sku = "";
                if (StringUtils.isNotBlank(orderItem.getStockSku())) {
                    sku = orderItem.getStockSku();
                }
                try {
                    Long productId = productService.getProductId(sku, companyId);
                    productAddReq.setProductId(productId);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                productAddReq.setCommoditySku(sku);
                productAddReq.setCount(orderItem.getQuantity());
                productAddReqs.add(productAddReq);
            }
        }
        OrderOutputPackageAddReq packageAddReq = new OrderOutputPackageAddReq();
        packageAddReq.setProductList(productAddReqs);
        packageAddReqs.add(packageAddReq);
        req.setSendDate(new Date());
        req.setOrderType(1);
        req.setShipmentType(0);
        req.setPackageList(packageAddReqs);
        req.setCompanyId(companyId);
        req.setPlatform("mabang");
        req.setReceiverName(mbOrderDetail.getBuyerName());
        ShopDo one = shopService.getOne(Wrappers.<ShopDo>lambdaQuery().eq(ShopDo::getCompanyId, companyId).last("limit 1"));
        req.setShopId(one.getId());
        req.setStorageId(storageId);
        req.setPlatformNumber(mbOrderDetail.getOrderId());
        req.setOrderNo(mbOrderDetail.getSalesRecordNumber());
        req.setTelPhone(mbOrderDetail.getPhone1());
        req.setArea(mbOrderDetail.getProvince());
        req.setCod(mbOrderDetail.getCodValue().intValue());
        return req;
    }

    private LambdaQueryWrapper<OrderMabangDo> queryBuild(OrderMbQueryBo bo) {
        LambdaQueryWrapper<OrderMabangDo> lqw = new LambdaQueryWrapper<>();
        lqw.in(CollUtil.isNotEmpty(bo.getIds()), OrderMabangDo::getId, bo.getIds());
        lqw.ge(Objects.nonNull(bo.getStartDate()), OrderMabangDo::getOrderDeliveryTime, bo.getStartDate());
        lqw.le(Objects.nonNull(bo.getEndDate()), OrderMabangDo::getOrderDeliveryTime, bo.getEndDate());
        lqw.and(
                StringUtils.isNotBlank(bo.getOrderId()),
                w -> w.eq(OrderMabangDo::getOrderId, bo.getOrderId()).eq(OrderMabangDo::getCompanyId, bo.getCompanyId())
        );
        lqw.eq(Objects.nonNull(bo.getCompanyId()), OrderMabangDo::getCompanyId, bo.getCompanyId());
        lqw.eq(StringUtils.isNotBlank(bo.getOrderStatus()), OrderMabangDo::getStatus, bo.getOrderStatus());
        lqw.eq(StringUtils.isNotBlank(bo.getShipMethod()), OrderMabangDo::getTWarehourseCode, bo.getShipMethod());
        lqw.orderByDesc(OrderMabangDo::getId, OrderMabangDo::getCreateTime);
        return lqw;
    }


}
